18.6 Agents:轻量级 Agent 循环实现
项目定位:这是 Anthropic 官方开源的教育性 Agent 实现,用不到 300 行代码展示 LLM Agent 的核心机制。非生产级 SDK,但作为学习和扩展的最佳起点。
1. 项目概览
1.1 为什么需要这个项目?
在 LangChain、CrewAI 等框架逐渐变得复杂的今天,很多开发者反而迷失在抽象层中,不理解 Agent 的底层原理。Anthropic 开源这个项目的目的很明确:
┌─────────────────────────────────────────────────────────────────┐
│ Agent 的本质是什么? │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 用户输入 ──▶ LLM 思考 ──▶ 决定调用工具? │
│ │ │
│ ┌───────────┴───────────┐ │
│ ▼ ▼ │
│ 是 (tool_use) 否 (text) │
│ │ │ │
│ 执行工具 返回响应 │
│ │ │
│ 结果返回给 LLM │
│ │ │
│ 循环继续 ◀───────────────────── │
│ │
└─────────────────────────────────────────────────────────────────┘这就是 Agent 的全部核心! 一个循环,仅此而已。
1.2 项目结构
bash
agents/
├── agent.py # 核心 Agent 类(< 300 行)
├── agent_demo.ipynb # 交互式演示 Notebook
├── __init__.py # 包初始化
├── tools/ # 工具实现
│ ├── __init__.py # 导出 6 个工具
│ ├── think.py # ThinkTool(思考工具)
│ ├── file_read.py # FileReadTool
│ ├── file_write.py # FileWriteTool
│ ├── code_execution.py # CodeExecutionServerTool
│ └── web_search.py # WebSearchServerTool
└── utils/ # 辅助工具
├── message_history.py # 消息历史管理
└── mcp.py # MCP 服务器连接1.3 技术栈
| 组件 | 说明 |
|---|---|
| Python 3.8+ | 基础运行环境 |
| anthropic | Claude API 官方 SDK |
| mcp | Model Context Protocol 库 |
| asyncio | 异步执行支持 |
2. 核心架构解析
2.1 Agent 类设计
python
from agents.agent import Agent
from agents.tools.think import ThinkTool
# 创建 Agent 实例
agent = Agent(
name="MyAgent",
system="You are a helpful assistant.",
tools=[ThinkTool()], # 本地工具
mcp_servers=[ # MCP 服务器工具(可选)
{
"type": "stdio",
"command": "python",
"args": ["-m", "mcp_server"],
},
]
)
# 运行 Agent
response = agent.run("What should I consider when buying a new laptop?")2.2 Agent 循环的实现
这是整个项目最核心的逻辑,_agent_loop 方法:
python
async def _agent_loop(self, messages: list) -> str:
"""
Agent 的核心循环:
1. 发送消息到 Claude API(包含工具定义)
2. 解析响应,检查是否有 tool_use
3. 如果有工具调用,执行工具并将结果返回给 Claude
4. 重复步骤 1-3,直到获得纯文本响应
"""
while True:
# 调用 Claude API
response = await self.client.messages.create(
model=self.config.model,
max_tokens=self.config.max_tokens,
system=self.system,
messages=messages,
tools=self._get_tool_definitions(), # 工具定义
)
# 检查是否有工具调用
tool_calls = self._extract_tool_calls(response)
if not tool_calls:
# 没有工具调用,返回最终文本响应
return self._extract_text(response)
# 执行所有工具调用
tool_results = []
for tool_call in tool_calls:
result = await self._execute_tool(tool_call)
tool_results.append(result)
# 将工具结果添加到消息历史
messages.append({"role": "assistant", "content": response.content})
messages.append({"role": "user", "content": tool_results})
# 继续循环2.3 工具执行流程
┌─────────────────────────────────────────────────────────────────┐
│ 工具执行流程 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Claude 返回: │
│ { │
│ "type": "tool_use", │
│ "id": "toolu_xxx", │
│ "name": "think", │
│ "input": {"thought": "Let me analyze this..."} │
│ } │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ Agent 查找工具:self.tools["think"] │ │
│ └─────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ 执行工具:tool.execute(input) │ │
│ └─────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ 返回结果给 Claude: │
│ { │
│ "type": "tool_result", │
│ "tool_use_id": "toolu_xxx", │
│ "content": "Thinking complete!" │
│ } │
│ │
└─────────────────────────────────────────────────────────────────┘3. 工具系统详解
3.1 内置工具一览
| 工具名称 | 功能描述 | 工具类型 |
|---|---|---|
| ThinkTool | 让 Agent 进行内部推理,不执行外部操作 | 本地工具 |
| FileReadTool | 读取文件内容 | 本地工具 |
| FileWriteTool | 写入文件内容 | 本地工具 |
| CodeExecutionServerTool | 执行代码片段 | MCP 服务器工具 |
| WebSearchServerTool | 网络搜索 | MCP 服务器工具 |
| Tool | 工具基类,用于自定义扩展 | 抽象类 |
3.2 ThinkTool 实现解析
ThinkTool 是最简单但最有教育意义的工具:
python
from agents.tools import Tool
class ThinkTool(Tool):
"""
思考工具:让 Agent 在行动前进行推理
这个工具体现了 "Chain of Thought" 的核心理念:
通过显式记录推理过程,增强模型的认知能力
"""
name = "think"
description = """
Use this tool for complex reasoning and to cache memories.
It does not fetch new information or change the database.
"""
input_schema = {
"type": "object",
"properties": {
"thought": {
"type": "string",
"description": "Your thought or reasoning"
}
},
"required": ["thought"]
}
def execute(self, thought: str) -> str:
"""执行思考(实际上只是记录并确认)"""
# 思考内容已被 Claude 记录在消息历史中
return "Thinking complete!"设计精妙之处:
- 零成本中间步骤:不调用外部 API,不产生副作用
- 强化推理能力:给模型一个"暂停思考"的机会
- 可追溯性:思考过程被完整记录在消息历史中
3.3 自定义工具开发
创建自己的工具非常简单:
python
from agents.tools import Tool
class WeatherTool(Tool):
name = "get_weather"
description = "Get current weather for a city"
input_schema = {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "City name"
}
},
"required": ["city"]
}
def execute(self, city: str) -> str:
# 实际实现:调用天气 API
return f"Weather in {city}: Sunny, 25°C"4. MCP 集成
4.1 什么是 MCP?
Model Context Protocol(模型上下文协议) 是 Anthropic 提出的开放标准,用于规范 LLM 与外部工具的交互方式:
┌─────────────────────────────────────────────────────────────────┐
│ MCP 架构 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────┐ MCP 协议 ┌──────────────────┐ │
│ │ Claude │ ◀─────────────────────▶ │ MCP Server │ │
│ │ Agent │ │ │ │
│ └──────────┘ │ - Web Search │ │
│ │ - Code Exec │ │
│ │ - Database │ │
│ │ - File System │ │
│ └──────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘4.2 MCP 服务器配置
python
agent = Agent(
name="EnhancedAgent",
system="You are a research assistant.",
tools=[ThinkTool()], # 本地工具
mcp_servers=[
# 标准输入/输出模式
{
"type": "stdio",
"command": "python",
"args": ["-m", "web_search_server"],
},
# SSE 模式(Server-Sent Events)
{
"type": "sse",
"url": "http://localhost:8080/mcp",
},
]
)4.3 MCP 的优势
| 优势 | 说明 |
|---|---|
| 标准化 | 统一的工具描述和调用协议 |
| 解耦 | 工具服务独立部署和扩展 |
| 安全 | 工具在隔离环境中运行 |
| 复用 | 同一 MCP 服务器可供多个 Agent 使用 |
5. 消息历史管理
5.1 上下文窗口限制
Claude 有上下文窗口限制(如 200k tokens),消息历史管理至关重要:
python
class Agent:
def _truncate_messages(self, messages: list) -> list:
"""
截断消息历史以适应上下文窗口
策略:
1. 始终保留系统提示
2. 始终保留最近的消息
3. 中间消息根据 token 数量动态截断
"""
total_tokens = self._count_tokens(messages)
max_tokens = self.config.context_window
if total_tokens <= max_tokens:
return messages
# 保留首尾,截断中间
return self._smart_truncate(messages, max_tokens)5.2 消息格式
python
# 完整的消息历史示例
messages = [
# 用户输入
{"role": "user", "content": "Search for Python tutorials"},
# Assistant 响应(包含工具调用)
{"role": "assistant", "content": [
{"type": "text", "text": "I'll search for Python tutorials."},
{"type": "tool_use", "id": "toolu_xxx", "name": "web_search",
"input": {"query": "Python tutorials 2025"}}
]},
# 工具结果
{"role": "user", "content": [
{"type": "tool_result", "tool_use_id": "toolu_xxx",
"content": "Found 10 results: ..."}
]},
# 最终响应
{"role": "assistant", "content": "Here are the best Python tutorials..."}
]6. 与其他框架的对比
6.1 代码量对比
| 框架 | 实现 Agent 循环的代码量 | 依赖包数量 |
|---|---|---|
| Claude Agents | ~300 行 | 2 个 |
| LangChain AgentExecutor | ~2000 行 | 50+ |
| CrewAI | ~1500 行 | 30+ |
| AutoGen | ~3000 行 | 40+ |
6.2 架构理念对比
┌─────────────────────────────────────────────────────────────────┐
│ Agent 框架设计理念 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Claude Agents LangChain CrewAI │
│ ┌────────────┐ ┌────────────┐ ┌────────────┐ │
│ │ 极简主义 │ │ 全能框架 │ │ 角色扮演 │ │
│ │ │ │ │ │ │ │
│ │ - 展示原理 │ │ - 抽象层多 │ │ - 多Agent │ │
│ │ - 易于理解 │ │ - 功能全面 │ │ - 任务分配 │ │
│ │ - 自由扩展 │ │ - 生态丰富 │ │ - 易于上手 │ │
│ └────────────┘ └────────────┘ └────────────┘ │
│ │
│ 适合:学习原理 适合:生产部署 适合:快速原型 │
│ 原型开发 企业应用 多Agent协作 │
│ │
└─────────────────────────────────────────────────────────────────┘6.3 什么时候选择 Claude Agents?
✅ 适合场景:
- 学习 Agent 核心原理
- 快速原型验证想法
- 不想引入重型框架
- Claude 专属项目
- 需要高度自定义
❌ 不适合场景:
- 需要多 LLM 支持
- 需要复杂工作流编排
- 需要成熟的监控工具
- 需要多 Agent 协作
7. 完整示例:构建研究助手
7.1 项目需求
构建一个能够:
- 搜索网络信息
- 阅读和分析文件
- 生成研究报告
的研究助手。
7.2 实现代码
python
import asyncio
from agents.agent import Agent
from agents.tools import ThinkTool, FileReadTool, FileWriteTool
# 创建研究助手 Agent
research_agent = Agent(
name="ResearchAssistant",
system="""You are a research assistant that helps users
gather and analyze information.
When given a research topic:
1. Use the think tool to plan your approach
2. Search for relevant information
3. Analyze and synthesize findings
4. Write a structured report
Always cite your sources and be thorough.""",
tools=[
ThinkTool(), # 思考和规划
FileReadTool(), # 读取参考资料
FileWriteTool(), # 写入报告
],
mcp_servers=[
# 添加网络搜索能力
{
"type": "stdio",
"command": "python",
"args": ["-m", "web_search_server"],
},
]
)
async def main():
# 运行研究任务
result = await research_agent.run_async(
"Research the latest developments in AI agents for 2025, "
"focusing on tool use and autonomous capabilities. "
"Write a report to 'ai_agents_report.md'"
)
print(result)
if __name__ == "__main__":
asyncio.run(main())7.3 运行流程
用户: Research the latest developments in AI agents...
Agent 思考: Let me plan my approach...
↓
工具调用: think({"thought": "I'll first search for recent AI agent news..."})
↓
工具调用: web_search({"query": "AI agents 2025 developments"})
↓
Agent 分析: Based on the search results...
↓
工具调用: think({"thought": "Key themes: tool use, autonomy, safety..."})
↓
工具调用: file_write({"path": "ai_agents_report.md", "content": "..."})
↓
Agent: I've completed the research and written the report to ai_agents_report.md.8. 最佳实践
8.1 工具设计原则
| 原则 | 说明 | 示例 |
|---|---|---|
| 单一职责 | 每个工具只做一件事 | read_file vs read_and_parse_file |
| 清晰描述 | 工具描述要让 LLM 理解用途 | 包含输入输出说明 |
| 错误处理 | 返回有意义的错误信息 | "File not found: {path}" |
| 幂等性 | 相同输入产生相同结果 | 避免副作用累积 |
8.2 系统提示设计
python
# 好的系统提示
system = """You are a coding assistant.
Available tools:
- think: Use for planning and reasoning before taking action
- file_read: Read file contents
- file_write: Write to files
Guidelines:
1. Always think before acting
2. Read files before modifying them
3. Explain your changes clearly
4. Handle errors gracefully
"""
# 避免的系统提示
system = "You are helpful." # 太简单,缺乏指导8.3 调试技巧
python
# 开启详细日志
agent = Agent(
name="DebugAgent",
system="...",
tools=[...],
verbose=True # 打印每次 API 调用和工具执行
)9. 扩展阅读
9.1 官方资源
- 项目仓库:anthropics/claude-quickstarts/agents
- 设计文档:Building Effective Agents
- MCP 规范:Model Context Protocol
9.2 相关项目
- Claude Agent SDK:生产级 Agent 开发框架
- Autonomous Coding:基于此模式的自主编码实现
- Computer Use Demo:桌面控制能力展示
10. 小结
核心收获
- Agent 本质是循环:发送消息 → 检查工具调用 → 执行工具 → 返回结果 → 重复
- 工具是 Agent 的手脚:通过工具,Agent 从"只会说话"变成"能做事"
- MCP 是标准化方案:统一工具协议,解耦 Agent 和工具实现
- 简单即是美:< 300 行代码实现完整 Agent 循环
与本书其他章节的关联
| 章节 | 关联知识点 |
|---|---|
| 18.1 Customer Support | RAG 集成到 Agent 工具 |
| 18.3 Computer Use | 工具的极致形态:操作电脑 |
| 18.4 Browser Use | 工具的另一形态:控制浏览器 |
| 18.5 Autonomous Coding | 基于此架构的完整编码系统 |
下一步:尝试克隆 claude-quickstarts 仓库,运行 agents/agent_demo.ipynb,亲手体验 Agent 循环的魔力!